#ifndef EGADU_DEC_H
#define EGADU_DEC_H

namespace eGaduLib
{

/**
    @mainpage
    @par O eGadu:
    eGadu jest to obiektowa biblioteka przeznaczona dla języka C++, umożliwiająca w prosty sposób wykorzystanie protokołu Gadu-Gadu.
    @author hck
    @date 08.01.2011
    @version 0.1.2
    @par Kontakt:
    Z wszelkimi pytaniami, sugestiami, itp. proszę słać e-maile na <michak.ny@gmail.com>
    @par TODO:
    Lista rzeczy do zrobienia: @ref todo
*/


/**
	Definicja typu zwracanego przez metody eGadu
*/
#define EGADU_RET int

/**
	@enum EGADU_RETURN
	@brief Definicje wartości zwracanych przez metody eGadu
*/
enum EGADU_RETURN
{
	/// Brak błędu
	EGADU_OK,

	/// Podano zły argument
	EGADU_INVALIDARG,
	/// Nieznany błąd
	EGADU_UNKNOWNERR,

	/// Połączenie internetowe jest niedostępne
	EGADU_NET_NOTAVAL,
	/// Połączenie internetowe zostało zerwane
	EGADU_NET_CORRPUTED,
	/// Nie udało się zalogować (prawdopodobnie podano zły numer lub hasło)
	EGADU_NET_LOGINFAIL,
};


#define PACK __attribute__((packed))

/**
	Definicje zawierające typy pakietów Gadu-Gadu.
*/
#define GG_WELCOME 0x0001
#define GG_LOGIN80 0x0031
#define GG_LOGIN_HASH_GG32 0x01
#define GG_LOGIN_HASH_SHA1 0x02
#define GG_LOGIN80_FAILED 0x0043
#define GG_LOGIN80_OK 0x0035
#define GG_NEW_STATUS80 0x0038
#define GG_NOTIFY_FIRST 0x000f
#define GG_NOTIFY_LAST 0x0010
#define GG_LIST_EMPTY 0x0012
#define GG_NOTIFY_REPLY80 0x0037
#define GG_SEND_MSG80 0x002d
#define GG_STATUS80 0x0036
#define GG_USER_DATA 0x0044
#define GG_ADD_NOTIFY 0x000d
#define GG_DISCONNECT_ACK 0x000d
#define GG_RECV_MSG80 0x002e
#define GG_SEND_MSG_ACK 0x0005
#define GG_PING 0x0008
#define GG_PONG 0x0007
#define GG_XML_DATA 0x002c
#define GG_XML_EVENT 0x0027

/**
    @brief Wyliczenie statusów Gadu-Gadu
*/
enum EGADU_STATUS
{
/// Niedostępny
 EGADU_STATUS_NOT_AVAIL = 0x0001,
/// Niedostępny z opisem
 EGADU_STATUS_NOT_AVAIL_DESCR = 0x4015,
/// PoGGadaj ze mną
 EGADU_STATUS_FFC = 0x0017,
/// PoGGadaj ze mną z opisem
EGADU_STATUS_FFC_DESCR = 0x4018,
/// Dostępny
EGADU_STATUS_AVAIL = 0x0002,
/// Dostępny z opisem
 EGADU_STATUS_AVAIL_DESCR = 0x4004,
/// Zaraz wracam
 EGADU_STATUS_BUSY = 0x0003,
/// Zaraz wracam z opisem
 EGADU_STATUS_BUSY_DESCR = 0x4005,
/// Nie przeszkadzać
 EGADU_STATUS_DND = 0x0021,
/// Nie przeszkadzać z opisem
 EGADU_STATUS_DND_DESCR = 0x4022,
/// Niewidoczny
 EGADU_STATUS_INVISIBLE = 0x0014,
/// Niewidoczny z opisem
 EGADU_STATUS_INVISIBLE_DESCR = 0x4016,
/// Zablokowany
 EGADU_STATUS_BLOCKED = 0x0006,
/// Maska bitowa oznaczająca ustawiony opis graficzny (tylko odbierane)
EGADU_STATUS_IMAGE_MASK = 0x0100,
/// Maska bitowa informująca serwer, że jeśli istnieje już inne połączenie na tym numerze to nasze ma przyjać jego stan (podany przez nas zostanie zignorowany). Jeśli połączenia innego nie ma, to ustawiany jest stan podany przez nas.
EGADU_STATUS_ADAPT_STATUS_MASK = 0x0400,
/// Maska bitowa oznaczająca ustawiony opis
EGADU_STATUS_DESCR_MASK = 0x4000,
/// Maska bitowa oznaczająca tryb tylko dla przyjaciół
EGADU_STATUS_FRIENDS_MASK =0x8000,
};

/// Zwykły kontakt
#define EGADU_USR_BUDDY 0x01
/// Kontakt w trybie tylko dla przyjaciół
#define EGADU_USR_FRIEND 0x02
/// Zablokowany kontakt
#define EGADU_USR_BLOCKED 0x04


struct gg_header {
	/// Typ pakietu
	int type;
	/// Rozmiar pakietu (bez nagłówka)
	int size;
} PACK ;


struct gg_welcome {
	/// Nagłówek
	gg_header hdr;
	/// Ziarno
	int seed;
} PACK ;

struct gg_login80 {
	/// Numer Gadu-Gadu
	int uin;
    /// Język
	char language[2];
    /// Rodzaj funkcji skrótu hasła
	char hash_type;
    /// Skrót hasła dopełniony \\0
	char hash[64];
    /// Początkowy status połączenia
	int status;
    /// Początkowe flagi połączenia
	int flags;
    /// Opcje protokołu
	int features;
    /// Lokalny adres połączeń bezpośrednich (nieużywany)
	int local_ip;
    /// Lokalny port połączeń bezpośrednich (nieużywany)
	short local_port;
    /// Zewnętrzny adres (nieużywany)
	int external_ip;
	/// Zewnętrzny port (nieużywany)
	short external_port;
    /// Maksymalny rozmiar grafiki w KB
	char image_size;
    /// Nieodkryto funkcji tego pola (0x64)
	char unknown1;
	/// Długość ciągu z wersją
	int version_len;
    /// Ciąg z werjsą
	char version[35];
    /// Rozmiar opisu
	int description_size;
    /// Opis (nie musi wystąpić)
	char *description;
} PACK ;


struct gg_login80_re {
	/// Nagłówek
	gg_header hdr;
	/// Nieodkryto funkcji tego pola (01 00 00 00)
	int unknown1;
} PACK ;


struct gg_new_status80 {
	/// Nowy status
	int status;
	/// Nowe flagi
	int flags;
	/// Rozmiar nowego opisu
	int description_size;
	/// Nowy opis (nie musi wystąpić)
	char *description;
} PACK ;


struct gg_notify {
	/// Numer Gadu-Gadu
	int uin;
	/// Rodzaj użytkownika
	char type;
} PACK ;


struct gg_notify_reply80 {
    /// Numer Gadu-Gadu
	int uin;
	/// Status
	int status;
	/// Opcje protokołu
	int features;
	/// Adres IP bezpośredniego połączenia (nieużywane)
	int remote_ip;
	/// Port bezpośredniego połączenia
	short remote_port;
	/// Maksymalny rozmiar obrazków w kb
	char image_size;
	/// Nieznane pole (0x00)
	char unknown1;
	/// Flagi
	int flags;
	/// Rozmiar opisu
	int description_size;
	/// Opis
	char *desc;
} PACK ;


struct gg_send_msg80 {
	/// Numer odbiorcy
	int recipient;
	/// Czas wysłania wiadomości
	int seq;
	/// Klasa wiadomości
	int Class;
	/// Położenie treści czystym tekstem
	int offset_plain;
	/// Położenie atrybutów
	int offset_attributes;
	/// Wiadomość w formacie HTML
	char *html_msg;
	/// Czysty tekst
	char *plain_msg;
	/// Atrybuty tekstu
	char *attributes;
} PACK ;


struct gg_user_data
{
    /// Typ informacji o kontakcie
	int type;
	/// Liczba struktur gg_user_data_user
	int num;
} PACK ;

struct gg_user_data_user
{
    /// Numer kontaktu
	int uin;
	/// Liczba struktur gg_user_data_user_attr
	int num;
} PACK ;

struct gg_user_data_user_attr
{
    /// Wielkość nazwy atrybutu
	int name_size;
	/// Nazwa atrybutu
	char *name;
	/// Typ atrybutu
	int type;
	/// Wielkość wartości atrybutu
	int value_size;
	/// Wartość atrybutu
	char *value;
} PACK ;

struct gg_recv_msg80 {
    /// Numer nadawcy
	int sender;
	/// Numer sekwencyjny
	int seq;
	/// Czas nadania
	int time;
	/// Klasa wiadomości
	int Class;
	/// Położenie czystego tekstu
	int offset_plain;
	/// Położenie atrybutów
	int offset_attributes;
	/// Treść w formacie HTML
	char *html_message;
	/// Czysty tekst
	char *plain_message;
	/// Atrybuty
	char *attributes;
} PACK ;

struct gg_send_msg_ack {
    /// Stan wiadomości
	int status;
	/// Numer odbiorcy
	int recipient;
	/// Numer sekwncyjny
	int seq;
} PACK ;

}

#endif
